package com.ssy.lingxi.logistics.serviceimpl;

import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.SelectVO;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.logistics.api.dto.response.CommonSelectResponse;
import com.ssy.lingxi.logistics.api.enums.CooperateTypeEnum;
import com.ssy.lingxi.logistics.entity.Company;
import com.ssy.lingxi.logistics.entity.FreightTemplate;
import com.ssy.lingxi.logistics.entity.ReceiverAddress;
import com.ssy.lingxi.logistics.entity.ShipperAddress;
import com.ssy.lingxi.logistics.model.enums.CommonStatusEnum;
import com.ssy.lingxi.logistics.model.enums.ReceiverAddressCreateTypeEnum;
import com.ssy.lingxi.logistics.model.request.SelectCompanyListRequest;
import com.ssy.lingxi.logistics.model.response.CompanyMemberSelectedResponse;
import com.ssy.lingxi.logistics.model.response.CompanySelectResponse;
import com.ssy.lingxi.logistics.model.response.ReceiverAddressSelectResponse;
import com.ssy.lingxi.logistics.model.response.ShipperAddressSelectResponse;
import com.ssy.lingxi.logistics.repository.CompanyRepository;
import com.ssy.lingxi.logistics.repository.FreightTemplateRepository;
import com.ssy.lingxi.logistics.repository.ReceiverAddressRepository;
import com.ssy.lingxi.logistics.repository.ShipperAddressRepository;
import com.ssy.lingxi.logistics.service.ISelectService;
import com.ssy.lingxi.logistics.util.LogisticsAddressUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 下拉数据服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/1/26
 */
@Service
public class SelectServiceImpl implements ISelectService {

    @Resource
    private CompanyRepository companyRepository;
    @Resource
    private ShipperAddressRepository shipperAddressRepository;
    @Resource
    private ReceiverAddressRepository receiverAddressRepository;
    @Resource
    private FreightTemplateRepository freightTemplateRepository;

    @Override
    public Wrapper<List<CommonSelectResponse>> listCompany(UserLoginCacheDTO loginUser, SelectCompanyListRequest request) {
        List<Company> all = companyRepository.findAll((Specification<Company>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            predicateList.add(cb.equal(root.get("status"), CommonStatusEnum.ENABLE.getCode()));
            if (Objects.nonNull(request.getCooperateType())) {
                predicateList.add(cb.equal(root.get("cooperateType"), request.getCooperateType()));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        });

        List<CommonSelectResponse> resultList = all.stream().map(e -> {
            CommonSelectResponse commonSelectResponse = new CommonSelectResponse();
            commonSelectResponse.setId(e.getId());
            commonSelectResponse.setName(e.getName());
            return commonSelectResponse;
        }).collect(Collectors.toList());
        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<SelectVO>> listMemberCompanyQuery(UserLoginCacheDTO loginUser, String name) {
        //根据条件查询
        List<Company> list = companyRepository.findByMemberIdAndRoleIdAndCooperateTypeAndNameContains(loginUser.getMemberId(), loginUser.getMemberRoleId(), CooperateTypeEnum.PLATFORM.getCode(), name, Sort.by("id"));
        //转换SelectVO实体
        List<SelectVO> resultList = list.stream().map(e -> {
            SelectVO selectVO = new SelectVO();
            selectVO.setId(e.getId());
            selectVO.setName(e.getName());
            return selectVO;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<SelectVO>> listPlatformMemberCompanyQuery(String name) {
        //根据条件查询
        List<Company> list = companyRepository.findByCooperateTypeAndNameContains(CooperateTypeEnum.PLATFORM.getCode(), name, Sort.by("id"));
        //转换SelectVO实体
        List<SelectVO> resultList = list.stream().map(e -> {
            SelectVO selectVO = new SelectVO();
            selectVO.setId(e.getId());
            selectVO.setName(e.getName());
            return selectVO;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<CompanySelectResponse>> listMemberCompany(UserLoginCacheDTO loginUser) {
        List<Company> all = companyRepository.findAll((Specification<Company>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            predicateList.add(cb.equal(root.get("status"), CommonStatusEnum.ENABLE.getCode()));
            predicateList.add(cb.equal(root.get("cooperateType"), CooperateTypeEnum.PLATFORM.getCode()));

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        });

        List<CompanySelectResponse> resultList = all.stream().map(e -> {
            CompanySelectResponse selectResponse = new CompanySelectResponse();
            selectResponse.setId(e.getId());
            selectResponse.setName(e.getName());
            selectResponse.setMemberId(e.getCompanyMemberId());
            selectResponse.setRoleId(e.getCompanyRoleId());
            return selectResponse;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<CompanyMemberSelectedResponse>> listMemberCompanySelected(UserLoginCacheDTO loginUser) {
        List<Company> companyList = companyRepository.findAllByMemberIdAndRoleIdAndCooperateType(loginUser.getMemberId(), loginUser.getMemberRoleId(), CooperateTypeEnum.PLATFORM.getCode());
        Map<Long, Set<Long>> memberRoleMap = companyList.stream().collect(Collectors.groupingBy(Company::getCompanyMemberId, Collectors.mapping(Company::getCompanyRoleId, Collectors.toSet())));


        List<CompanyMemberSelectedResponse> responseList = new ArrayList<>();
        for (Map.Entry<Long, Set<Long>> entry : memberRoleMap.entrySet()) {
            Long memberId = entry.getKey();
            for (Long roleId : entry.getValue()) {
                CompanyMemberSelectedResponse response = new CompanyMemberSelectedResponse();
                response.setMemberId(memberId);
                response.setRoleId(roleId);
                responseList.add(response);
            }
        }

        return Wrapper.success(responseList);
    }

    @Override
    public Wrapper<List<ShipperAddressSelectResponse>> listShipperAddress(Long memberId, Long roleId) {
        List<Sort.Order> orders = Arrays.asList(new Sort.Order(Sort.Direction.DESC, "isDefault"), new Sort.Order(Sort.Direction.DESC, "createTime"));
        List<ShipperAddress> all = shipperAddressRepository.findAllByMemberIdAndRoleId(memberId, roleId, Sort.by(orders));
        List<ShipperAddressSelectResponse> resultList = all.stream().map(e -> {
            ShipperAddressSelectResponse response = new ShipperAddressSelectResponse();
            String fullAddress = LogisticsAddressUtil.contractFullAddress(e.getProvinceName(), e.getCityName(), e.getDistrictName(), e.getStreetName(), e.getAddress());
            response.setFullAddress(fullAddress);
            response.setId(e.getId());
            response.setShipperName(e.getShipperName());
            response.setProvinceCode(e.getProvinceCode());
            response.setProvinceName(e.getProvinceName());
            response.setCityCode(e.getCityCode());
            response.setCityName(e.getCityName());
            response.setDistrictCode(e.getDistrictCode());
            response.setDistrictName(e.getDistrictName());
            response.setStreetCode(e.getStreetCode());
            response.setStreetName(e.getStreetName());
            response.setAddress(e.getAddress());
            response.setPhone(e.getPhone());
            response.setIsDefault(e.getIsDefault());
            return response;
        }).collect(Collectors.toList());
        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<SelectVO>> listShipperSelect(UserLoginCacheDTO loginUser, String name) {
        //根据条件查询
        Pageable pageable = PageRequest.of(0, Constants.SELECT_COUNT, Sort.by("id"));
        Page<ShipperAddress> page = shipperAddressRepository.findByMemberIdAndRoleIdAndShipperNameContains(loginUser.getMemberId(), loginUser.getMemberRoleId(), name, pageable);
        //转换SelectVO实体
        List<SelectVO> resultList = page.getContent().stream().map(e -> {
            SelectVO selectVO = new SelectVO();
            selectVO.setId(e.getId());
            selectVO.setName(e.getShipperName());
            return selectVO;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<ReceiverAddressSelectResponse>> listReceiverAddress(Long memberId, Long roleId) {
        List<Sort.Order> orders = Arrays.asList(new Sort.Order(Sort.Direction.DESC, "isDefault"), new Sort.Order(Sort.Direction.DESC, "createTime"));

        List<ReceiverAddress> all = receiverAddressRepository.findAll((Specification<ReceiverAddress>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId"), memberId));
            predicateList.add(cb.equal(root.get("roleId"), roleId));
            predicateList.add(cb.equal(root.get("createType"), ReceiverAddressCreateTypeEnum.LOGISTICS.getCode()));

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, Sort.by(orders));

        List<ReceiverAddressSelectResponse> resultList = all.stream().map(e -> {
            ReceiverAddressSelectResponse receiverAddressSelectResponse = new ReceiverAddressSelectResponse();
            receiverAddressSelectResponse.setId(e.getId());
            receiverAddressSelectResponse.setReceiverName(e.getReceiverName());
            receiverAddressSelectResponse.setProvinceCode(e.getProvinceCode());
            receiverAddressSelectResponse.setProvinceName(e.getProvinceName());
            receiverAddressSelectResponse.setCityCode(e.getCityCode());
            receiverAddressSelectResponse.setCityName(e.getCityName());
            receiverAddressSelectResponse.setDistrictCode(e.getDistrictCode());
            receiverAddressSelectResponse.setDistrictName(e.getDistrictName());
            receiverAddressSelectResponse.setStreetCode(e.getStreetCode());
            receiverAddressSelectResponse.setStreetName(e.getStreetName());
            receiverAddressSelectResponse.setAddress(e.getAddress());
            receiverAddressSelectResponse.setPostalCode(e.getPostalCode());
            receiverAddressSelectResponse.setAreaCode(e.getAreaCode());
            receiverAddressSelectResponse.setPhone(e.getPhone());
            receiverAddressSelectResponse.setTel(e.getTel());
            receiverAddressSelectResponse.setIsDefault(e.getIsDefault());

            String fullAddress = LogisticsAddressUtil.contractFullAddress(e.getProvinceName(), e.getCityName(), e.getDistrictName(), e.getStreetName(), e.getAddress());
            receiverAddressSelectResponse.setFullAddress(fullAddress);
            return receiverAddressSelectResponse;
        }).collect(Collectors.toList());
        return Wrapper.success(resultList);
    }

    @Override
    public Wrapper<List<CommonSelectResponse>> listFreightTemplate(UserLoginCacheDTO loginUser) {
        List<FreightTemplate> all = freightTemplateRepository.findAllByStatusAndMemberIdAndRoleId(CommonStatusEnum.ENABLE.getCode(), loginUser.getMemberId(), loginUser.getMemberRoleId());
        List<CommonSelectResponse> resultList = all.stream().map(e -> {
            CommonSelectResponse commonSelectResponse = new CommonSelectResponse();
            commonSelectResponse.setId(e.getId());
            commonSelectResponse.setName(e.getName());
            return commonSelectResponse;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }
}